package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener.global;

import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceStatusEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmConstants;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.MagicApiConfigProcessInstanceEventEnum;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.magicApiConfig.BpmCallMagicApiService;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.magicApiConfig.dto.MagicApiConfigDto;
import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils;
import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService;
import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService;
import com.google.common.collect.ImmutableSet;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.*;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener;
import org.flowable.engine.delegate.event.FlowableCancelledEvent;
import org.flowable.engine.delegate.event.FlowableProcessStartedEvent;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @description: 流程Event全局监听器
 */
@Component
@Slf4j
public class GlobalProcistEventListener extends AbstractFlowableEngineEventListener {

    @Resource
    @Lazy
    private BpmProcessInstanceService processInstanceService;
    @Resource
    @Lazy
    private BpmModelService bpmModelService;
    @Resource
    @Lazy
    private BpmCallMagicApiService bpmCallMagicApiService;

    public static final Set<FlowableEngineEventType> PROCESS_INSTANCE_EVENTS = ImmutableSet.<FlowableEngineEventType>builder()
            // 流程创建
            .add(FlowableEngineEventType.PROCESS_CREATED)
            // 流程开始
            .add(FlowableEngineEventType.PROCESS_STARTED)
            // 流程完成
            .add(FlowableEngineEventType.PROCESS_COMPLETED)
            // 流程取消
            .add(FlowableEngineEventType.PROCESS_CANCELLED)

            .build();

    public GlobalProcistEventListener(){
        super(PROCESS_INSTANCE_EVENTS);
    }

    @Override
    protected void processCreated(FlowableEngineEntityEvent event) {
        ExecutionEntityImpl execution = (ExecutionEntityImpl) event.getEntity();
        ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
        BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(execution.getProcessDefinitionId());
        BaseElement source = bpmnModel.getMainProcess();
        List<MagicApiConfigDto> magicApiConfigDtoList = bpmCallMagicApiService.initMagicApiConfig(source);
        magicApiConfigDtoList.stream().forEach(magicApiConfigDto -> {
            if(MagicApiConfigProcessInstanceEventEnum.CREATED.getEvent().equals(magicApiConfigDto.getEvent())){
                callBpmCallMagicApiService( magicApiConfigDto,processInstance);
            }
        });

        log.info("流程创建，流程实例id为：" + processInstance.getProcessInstanceId());

    }
    @Override
    protected void processStarted(FlowableProcessStartedEvent event) {
        ExecutionEntityImpl execution = (ExecutionEntityImpl) event.getEntity();
        ProcessInstance processInstance = processInstanceService.getProcessInstance(execution.getProcessInstanceId());
        BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(execution.getProcessDefinitionId());
        BaseElement source = bpmnModel.getMainProcess();
        List<MagicApiConfigDto> magicApiConfigDtoList = bpmCallMagicApiService.initMagicApiConfig(source);
        magicApiConfigDtoList.stream().forEach(magicApiConfigDto -> {
            if(MagicApiConfigProcessInstanceEventEnum.STARTED.getEvent().equals(magicApiConfigDto.getEvent())){
                callBpmCallMagicApiService( magicApiConfigDto,processInstance);
            }
        });

        log.info("流程开始，流程实例id为：" + processInstance.getProcessInstanceId());
    }

    @Override
    protected void processCompleted(FlowableEngineEntityEvent event) {
        ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId());
        BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(event.getProcessDefinitionId());
        BaseElement source = bpmnModel.getMainProcess();
        List<MagicApiConfigDto> magicApiConfigDtoList = bpmCallMagicApiService.initMagicApiConfig(source);
        magicApiConfigDtoList.stream().forEach(magicApiConfigDto -> {
            if(MagicApiConfigProcessInstanceEventEnum.COMPLETED.getEvent().equals(magicApiConfigDto.getEvent())){
                callBpmCallMagicApiService( magicApiConfigDto,processInstance);
            }
        });

        log.info("流程结束，流程实例id为：" + processInstance.getProcessInstanceId());
    }


    @Override
    protected void processCancelled(FlowableCancelledEvent event) {
        ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId());
        BpmnModel bpmnModel = bpmModelService.getBpmnModelByDefinitionId(processInstance.getProcessDefinitionId());
        BaseElement source = bpmnModel.getMainProcess();
        List<MagicApiConfigDto> magicApiConfigDtoList = bpmCallMagicApiService.initMagicApiConfig(source);
        Integer processInstanceStatus = FlowableUtils.getProcessInstanceStatus(processInstance);
        magicApiConfigDtoList.stream().forEach(magicApiConfigDto -> {
            magicApiConfigDto.getFields().put(BpmConstants.PROCESS_INSTANCE_VARIABLE_STATUS, processInstanceStatus);
            if(BpmProcessInstanceStatusEnum.CANCEL.getStatus().equals(processInstanceStatus)
                    && MagicApiConfigProcessInstanceEventEnum.CANCELLED.getEvent().equals(magicApiConfigDto.getEvent())
            ){
                callBpmCallMagicApiService( magicApiConfigDto,processInstance);
            }
            else if(BpmProcessInstanceStatusEnum.REJECT.getStatus().equals(processInstanceStatus)
                    && MagicApiConfigProcessInstanceEventEnum.REJECTED.getEvent().equals(magicApiConfigDto.getEvent())
            ){
                callBpmCallMagicApiService( magicApiConfigDto,processInstance);
            }
        });

        log.info("流程取消，流程实例id为：" + processInstance.getProcessInstanceId());
    }


    private void callBpmCallMagicApiService(MagicApiConfigDto magicApiConfigDto,ProcessInstance processInstance){
        magicApiConfigDto.getFields()
                .put("processInstanceId", processInstance.getProcessInstanceId());
        magicApiConfigDto.getFields()
                .put("processDefinitionKey", processInstance.getProcessDefinitionKey());
        magicApiConfigDto.getFields()
                .put("businessKey", processInstance.getBusinessKey());
        magicApiConfigDto.getFields()
                .put("event", magicApiConfigDto.getEvent());

        magicApiConfigDto.getFields().putAll(processInstance.getProcessVariables());

        bpmCallMagicApiService.callMagicApiByConfig(magicApiConfigDto);
    }


}
